﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using Ingr.SP3D.Reports.Middle;
using Ingr.SP3D.Common.Middle;
using Ingr.SP3D.Drawings.Middle;
using Ingr.SP3D.Common.Middle.Services.Hidden;
using Ingr.SP3D.Common.Middle.Services;
using Ingr.SP3D.Route.Middle;
using Ingr.SP3D.Support.Middle;
using Ingr.SP3D.Structure.Middle;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
using Ingr.SP3D.ReferenceData.Middle;
using System.Reflection;
using Ingr.SP3D.Equipment.Middle;
using System.IO;

namespace SWS.PIP.Label
{
	/// <summary>
	/// 定长管材料清单
	/// </summary>
	public class InstListFromViewWithoutSpoolLabel1 : QueryInterpreter
	{
		DataTable mDataTable = new DataTable();
		static string mIgnoredSpecs = "CZ|CS";
		DataTable mOneSocketPipeConfigDT = null;
		string mMode = "OneSocket"; //null or OneSocket

		public override DataTable Execute(string action, string argument)
		{
			mMode = action;

			//1 初始化表头
			mDataTable.Columns.Add("Data", typeof(String));

			//1.1 设计阶段时，直接返回表头
			if (EvaluateOnly)
				return mDataTable;

			//2 获取数据
			string sResultData = "";
			try
			{
				sResultData = GetBomListFromView();
			}
			catch (System.Exception ex)
			{
				//将错误显示到lable
				sResultData = ex.Message + "\n" + ex.StackTrace;
			}
			finally
			{
				DataRow row = mDataTable.NewRow();
				row.SetField("Data", sResultData);
				mDataTable.Rows.Add(row);
			}

			//3 返回数据
			return mDataTable;
		}

		/// <summary>
		/// 从view上获取bom信息
		/// </summary>
		/// <returns>指定格式数据字符</returns>
		private string GetBomListFromView()
		{
			string sResult = "";

			if (InputObjects.Count == 0)
			{
				return "Input error.";
			}

			//类型核对
			BusinessObject oGraphicView = InputObjects[0];
			if (!oGraphicView.SupportsInterface("IJDDwgGraphicView"))
			{
				return "Input object not view object.";
			}

			//获取View中对象
			SQLDBConnection oSQLDBConn = new SQLDBConnection(oGraphicView.DBConnection.Server, oGraphicView.DBConnection.Name);
			string sSQL = @"select distinct nameItem.Oid
							from DRAWNGDrawingMap drawMap
							join JNamedItem nameItem on nameItem.Oid = drawMap.str3D_DBID
							where (
							nameItem.oid in (select oid from JHgrSupport)
							or nameItem.oid in (select oid from JRteCompOccur)
							or nameItem.oid in (select oid from JRteSpecialtyOccur)
							or nameItem.oid in (select oid from JRtePipePart)
							or nameItem.oid in (select oid from JHgrSupportComponent)
							or nameItem.oid in (select oid from SPSSlabEntity)
							)
							and drawMap.strViewDBID = '$$'";
			sSQL = sSQL.Replace("$$", oGraphicView.ObjectID.Replace("{", "").Replace("}", ""));
			DataTable dtCompsInView = oSQLDBConn.ExecuteSelectQuery(sSQL);
			if (dtCompsInView.Rows.Count == 0)
			{
				return "No component need to be reported in current view.";
			}

			//整理数据
			List<BusinessObject> oGeneralPipeStockList = new List<BusinessObject>();
			List<BusinessObject> oOneSocketPipeStockList = new List<BusinessObject>();
			List<BusinessObject> oPipeGeneralCompList = new List<BusinessObject>();
			List<BusinessObject> oPipeOneSocketCompList = new List<BusinessObject>();
			List<string> oSupportList = new List<string>();
			DataTable dtErection = new DataTable();
			dtErection.Columns.Add("Code");
			dtErection.Columns.Add("Desc");
			foreach (DataRow row in dtCompsInView.Rows)
			{
				//从对象Oid构建出BussinessObject
				string sCurrOid = row["Oid"].ToString();
				if (oGraphicView.DBConnection.DBProvider == "MSSQL" && !sCurrOid.StartsWith("{"))
				{
					sCurrOid = "{" + sCurrOid + "}";
				}

				BOMoniker bomoniker = oGraphicView.DBConnection.GetBOMonikerFromDbIdentifier(sCurrOid);
				if (bomoniker == null)
				{
					return $"Get object{sCurrOid}'s BOMoniker from view{oGraphicView.ObjectID} failed.";
				}

				BusinessObject oCurrObject = oGraphicView.DBConnection.WrapSP3DBO(bomoniker);
				if (oCurrObject == null)
				{
					return $"Get object{sCurrOid}'s BusinessObject from view{oGraphicView.ObjectID} failed.";
				}

				//判断类型
				//管材
				if (oCurrObject is PipeStockPart && !IsBelongToIgnoredSpecs(oCurrObject))
				{
					if (mMode == "OneSocket" && IsOneSocketPipePart(oCurrObject))
					{
						oOneSocketPipeStockList.Add(oCurrObject);
					}
					else
					{
						oGeneralPipeStockList.Add(oCurrObject);	
					}
				}
				//内场管部件
				else if ((oCurrObject is Ingr.SP3D.Route.Middle.PipeComponent || oCurrObject is PipeSpecialty || oCurrObject is PipeInstrument) &&
					!IsBelongToIgnoredSpecs(oCurrObject) &&
					!IsErection(oCurrObject))
				{

					if (mMode == "OneSocket" && IsOneSocketPipePart(oCurrObject))
					{
						oPipeOneSocketCompList.Add(oCurrObject);
					}
					else
					{
						oPipeGeneralCompList.Add(oCurrObject);
					}
				}
				//外场阀附件/外场安装件
				else if ((oCurrObject is Ingr.SP3D.Route.Middle.PipeComponent ||
					oCurrObject is PipeSpecialty ||
					oCurrObject is PipeInstrument) &&
					IsErection(oCurrObject))
				{
					string sName = "";
					string sDesc = "";
					GetErectionNameAndDesc(oCurrObject, ref sName, ref sDesc);
					if (sName == "")
					{
						sName = oCurrObject.ObjectID;
					}
					DataRow drNewRow = dtErection.NewRow();
					drNewRow["Code"] = sName;
					drNewRow["Desc"] = sDesc;
					dtErection.Rows.Add(drNewRow);
				}
				else if (oCurrObject is Slab)
				{
					Slab oSlab = oCurrObject as Slab;
					string sSlabName = oSlab.Name;
					Part oComposition = oSlab.Composition;
					string sCompositionName = oComposition.PartNumber;
					string sDesc = "";
					if (sSlabName.Contains("ASP"))//圆形垫板
					{
						double dThk = oSlab.Thickness;
						double dRadius = Math.Sqrt(oSlab.TotalVolume / (dThk * Math.PI));

						sDesc = "防冲击板 " + ((Math.Round(dRadius * 1000, 0)) * 2).ToString() + "*" + ((Math.Round(dThk * 1000, 0)) * 2).ToString() + " " + sCompositionName;
					}
					else if (sSlabName.Contains("BKT"))
					{
						sDesc = "翅板 " + sCompositionName;
					}
					else
					{
						sDesc = "未定义类型。Slab板仅定义了ASP/BKT类型的描述。";
					}

					DataRow drNewRow = dtErection.NewRow();
					drNewRow["Code"] = sSlabName;
					drNewRow["Desc"] = sDesc;
					dtErection.Rows.Add(drNewRow);
				}
				//支架/外场安装件
				else if (oCurrObject is SupportComponent ||
					oCurrObject is Support)
				{
					Support oSupport = null;
					if (oCurrObject is Support)
					{
						oSupport = oCurrObject as Support;
					}
					else
					{
						SupportComponent oSupportComp = oCurrObject as SupportComponent;
						oSupport = oSupportComp.AssemblyParent as Support;
					}

					if (oSupport != null && oSupport.AssemblyParent != null &&
						(oSupport.AssemblyParent.ToString().Contains("15.") ||
						oSupport.AssemblyParent.ToString().Contains("31.") ||
						oSupport.AssemblyParent.ToString().Contains("35.") ||
						oSupport.AssemblyParent.ToString().Contains("40.") ||
						oSupport.AssemblyParent.ToString().Contains("45.")))
					{
						if (!oSupportList.Contains(oSupport.Name))
						{
							oSupportList.Add(oSupport.Name);
						}
					}
					else if (oSupport != null && oSupport.AssemblyParent == null)
					{
						DataRow drNewRow = dtErection.NewRow();
						drNewRow["Code"] = oSupport.Name;
						drNewRow["Desc"] = "支架没有装配到节点，无法判断支架类型。";
						dtErection.Rows.Add(drNewRow);
					}
					else
					{
						string sName = "";
						string sDesc = "";
						GetErectionNameAndDesc(oCurrObject, ref sName, ref sDesc);
						if (sName == "")
						{
							sName = oCurrObject.ObjectID;
						}

						DataRow drNewRow = dtErection.NewRow();
						drNewRow["Code"] = sName;
						drNewRow["Desc"] = sDesc;
						dtErection.Rows.Add(drNewRow);
					}
				}	
			}

			//构建输出
			sResult = "管道清单：\n\n";
			if (mMode == "OneSocket")
			{
				sResult += "   件号   | 数量 |     物资编码     |                     物资描述                       \n\n";

				DataTable oOneSocketPipeListDT = GetOneSocketPipePartDataTable(oOneSocketPipeStockList);
				string sOneSocketPipeStockList = CommonFunctions.GetLeftAlignReportFromDT(oOneSocketPipeListDT, new int[] { 12, 6, 14, 48 });
				sResult += sOneSocketPipeStockList;

				DataTable oPipeCompListDT = GetOneSocketPipePartDataTable(oPipeOneSocketCompList, true);
				string sPipeCompList = CommonFunctions.GetLeftAlignReportFromDT(oPipeCompListDT, new int[] { 12, 6, 14, 48 });
				sResult += (sPipeCompList + "\n\n");
			}
			else
			{
				sResult += "     物资编码     |                     物资描述                       | 通径 | 数量 \n\n";

				DataTable oPipeListDT = GetNoneSpoolPipePartDataTable(oGeneralPipeStockList);
				string sPipeStockList = CommonFunctions.GetLeftAlignReportFromDT(oPipeListDT, new int[] { 18, 50, 6, 6 });
				sResult += sPipeStockList;

				DataTable oPipeCompListDT = GetNoneSpoolPipePartDataTable(oPipeOneSocketCompList, true);
				string sPipeCompList = CommonFunctions.GetLeftAlignReportFromDT(oPipeCompListDT, new int[] { 18, 50, 6, 6 });
				sResult += (sPipeCompList + "\n\n");
			}


			sResult += "支架及护圈清单：（共" + oSupportList.Count.ToString() + "个）\n\n";
			oSupportList.Sort();
			ChangeToSWSListStyle(ref oSupportList);
			DataTable dtSupportTable = new DataTable();
			dtSupportTable.Columns.Add("Support");
			foreach (var sSupport in oSupportList)
			{
				DataRow dtNewRow = dtSupportTable.NewRow();
				dtNewRow["Support"] = sSupport;
				dtSupportTable.Rows.Add(dtNewRow);
			}
			string sSupportList = CommonFunctions.GetLeftAlignReportFromDT(dtSupportTable, new int[] { 86 });
			sResult += (sSupportList + "\n\n");

			sResult += "阀件附件清单：（共" + dtErection.Rows.Count + "个）\n\n";
			string sErectionList = CommonFunctions.GetLeftAlignReportFromDT(dtErection, new int[] { 18, 66});
			sResult += sErectionList + "\n";

			return sResult;
		}

		/// <summary>
		/// 计算定长管管材数据
		/// </summary>
		/// <param name="oOneSocketPipeStockList"></param>
		/// <returns></returns>
		private DataTable GetOneSocketPipePartDataTable(List<BusinessObject> oOneSocketPipeStockList, bool bIsComp = false)
		{
			DataTable oResultDT = new DataTable();
			oResultDT.Columns.Add("PartNumber", typeof(string));
			oResultDT.Columns.Add("Quantity", typeof(int));
			oResultDT.Columns.Add("MaterialCode", typeof(string));
			oResultDT.Columns.Add("MaterialDesc", typeof(string));
			
			//获取管材数据
			double dLength = 0.0;
			string sPartNumber = "";
			string sMaterialCode = "";
			string sMaterialDesc = "";
			string sNote1 = "";
			Part oPipePart = null;
			foreach (var oBO in oOneSocketPipeStockList)
			{
				oPipePart = GetRefPart(oBO) as Part;
				if (oPipePart == null)
				{
					sPartNumber = oBO.ToString();
					sMaterialDesc = "No catalog data...";
				}
				else if (bIsComp)
				{
					sMaterialDesc = GetCompMatDesc(oPipePart);
					sMaterialCode = GetCompMatCode(oPipePart);
					sNote1 = GetCompPartNote1(oPipePart);
					sPartNumber = sNote1;
				}
				else
				{
					sPartNumber = GetCompPartNumber(oPipePart);
					sNote1 = GetCompPartNote1(oPipePart);
					dLength = GetPipeCutLength(oBO);

					//将定长管长度转换为数量，并获取配置文件中的描述
					int iLength = FindOneSockectCodeAndDescFromConfig(dLength, sPartNumber, ref sMaterialCode, ref sMaterialDesc);
					sPartNumber = sNote1 + "-" + iLength.ToString();
				}

				DataRow drNewRow = oResultDT.NewRow();
				drNewRow["PartNumber"] = sPartNumber;
				drNewRow["Quantity"] = 1;
				drNewRow["MaterialCode"] = sMaterialCode;
				drNewRow["MaterialDesc"] = sMaterialDesc;
				oResultDT.Rows.Add(drNewRow);
			}

			//排序汇总
			var myTable = from t in oResultDT.AsEnumerable()
						  group t by new
						  {
							  PartNumber = t.Field<string>("PartNumber"),
							  MaterialCode = t.Field<string>("MaterialCode"),
							  MaterialDesc = t.Field<string>("MaterialDesc"),
						  } into x
						  orderby x.Key.MaterialCode
						  select new
						  {
							  x.Key.PartNumber,
							  Quantity = x.Sum(k => k.Field<double>("Quantity")),
							  x.Key.MaterialCode,
							  x.Key.MaterialDesc,
						  };
			oResultDT = CommonFunctions.LINQToDataTable(myTable);

			return oResultDT;
		}

		/// <summary>
		/// 将定长管的长度，物质代码，描述按配置文件中的配置进行转换
		/// </summary>
		/// <param name="dLength"></param>
		/// <param name="sMaterialCode"></param>
		/// <param name="sMaterialDesc"></param>
		private int FindOneSockectCodeAndDescFromConfig(double dLength, string sPartNumber, ref string sMaterialCode, ref string sMaterialDesc)
		{
			//查找匹配长度
			var myTable = from t in mOneSocketPipeConfigDT.AsEnumerable()
						  where t.Field<string>("PartNumber") == sPartNumber
						  select t.Field<int>("Length");
			double dSub = 0.0;//管实际长度和规格长度差值
			double dMinSub = 100000;
			int iLength = 0;
			foreach (var item in myTable)
			{
				dSub = item - dLength;
				if (Math.Abs(dSub) <= 10)//10mm内的按当前长度计算
				{
					iLength = item;
					break;
				}
				else if (dSub > 0 && dSub < dMinSub)
				{
					iLength = item;
					dMinSub = dSub;
				}
			}

			//按当前长度和材料编码匹配配置
			var tempResult = from t in mOneSocketPipeConfigDT.AsEnumerable()
							 where t.Field<string>("PartNumber") == sPartNumber && t.Field<int>("Length") == iLength
							 select t;
			if (tempResult.Count<DataRow>() == 0)
			{
				throw new Exception($"材料编码{sPartNumber}，管长{dLength}mm，没有匹配到配置数据，请检查...\\CustomerDef\\Piping\\Data\\OneSocketPipes.def配置文件。");
			}
			else if (tempResult.Count<DataRow>() > 1)
			{
				throw new Exception($"材料编码{sPartNumber}，管长{dLength}mm，匹配到多条配置数据，请检查...\\CustomerDef\\Piping\\Data\\OneSocketPipes.def配置文件。");
			}
			else
			{
				sMaterialCode = (tempResult.First<DataRow>())["MatCode"].ToString();
				sMaterialDesc = (tempResult.First<DataRow>())["MatDesc"].ToString();
			}

			return iLength;
		}

		/// <summary>
		/// 判断管材是否为定长管，判断依据材料等级为配置文件中相应等级
		/// </summary>
		/// <param name="oCurrObject"></param>
		/// <returns></returns>
		private bool IsOneSocketPipePart(BusinessObject oCurrObject)
		{
			//获取管材的材料等级
			ReadOnlyCollection<BusinessObject> oRelList = oCurrObject.GetRelationship("OwnsParts", "Owner").TargetObjects;
			PipeRun oPipeRun = oRelList[0] as PipeRun;
			string sSpecName = oPipeRun.Specification.DisplayName;

			//获取配置
			if (mOneSocketPipeConfigDT == null)
			{
				string sConfigPath = MiddleServiceProvider.SiteMgr.ActiveSite.ActivePlant.PlantCatalog.SymbolShare + "\\CustomerDef\\Piping\\Data\\OneSocketPipes.def";

				//读取配置数据
				if (File.Exists(sConfigPath))
				{
					mOneSocketPipeConfigDT = new DataTable();
					mOneSocketPipeConfigDT.Columns.Add("Spec", typeof(string));
					mOneSocketPipeConfigDT.Columns.Add("PartNumber", typeof(string));
					mOneSocketPipeConfigDT.Columns.Add("Length", typeof(int));
					mOneSocketPipeConfigDT.Columns.Add("MatCode", typeof(string));
					mOneSocketPipeConfigDT.Columns.Add("MatDesc", typeof(string));
					mOneSocketPipeConfigDT.Columns.Add("Weight", typeof(double));

					using (StreamReader sr = File.OpenText(sConfigPath))
					{
						string sLine;
						string pattern = "[|]";
						int iLine = 0;
						while ((sLine = sr.ReadLine()) != null)
						{
							iLine++;
							string[] arrLineData = Regex.Split(sLine, pattern);
							if (arrLineData.Length == 6)
							{
								DataRow row = mOneSocketPipeConfigDT.NewRow();
								row["Spec"] = arrLineData[0];
								row["PartNumber"] = arrLineData[1];
								row["Length"] = Convert.ToInt32(arrLineData[2]);
								row["MatCode"] = arrLineData[3];
								row["MatDesc"] = arrLineData[4];
								row["Weight"] = Convert.ToDouble(arrLineData[5]);

								mOneSocketPipeConfigDT.Rows.Add(row);
							}
							else
							{
								throw new Exception($"定长管配置文件（{sConfigPath}）中，行{iLine}，配置格式错误。请检查配置。");
							}
						}
					}


				}
				else
				{
					throw new Exception($"定长管配置文件（{sConfigPath}）不存在。请检查配置。");
				}
			}

			//查找管材所属等级是否在配置文件中存在
			var myTable = from t in mOneSocketPipeConfigDT.AsEnumerable()
						  where t.Field<string>("Spec") == sSpecName
						  select new
						  {
							  Spec = t.Field<string>("Spce")
						  };

			DataTable oResultDT = CommonFunctions.LINQToDataTable(myTable);
			if (oResultDT.Rows.Count > 0)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		/// <summary>
		/// 判断管部件是否属于不统计的材料等级
		/// </summary>
		/// <param name="oCurrObject"></param>
		/// <returns></returns>
		private bool IsBelongToIgnoredSpecs(BusinessObject oCurrObject)
		{
			ReadOnlyCollection<BusinessObject> oTargets = oCurrObject.GetRelationship("OwnsParts", "Owner").TargetObjects;
			if (oTargets.Count > 0)
			{
				PipeRun oPipeRun = oTargets[0] as PipeRun;
				string sSpecName = oPipeRun.Specification.DisplayName;

				if (Regex.Matches(sSpecName, mIgnoredSpecs).Count != 0)
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// 构建一个去除重复前缀的列表
		/// </summary>
		/// <param name="oStringList"></param>
		private void ChangeToSWSListStyle(ref List<string> oStringList)
		{
			if (oStringList.Count >= 2)
			{
				string sPrefixString = "";
				string sCurrString = "";
				string sNextString = "";
				string[] arrSplitString = null;
				for (int i = 0; i < oStringList.Count-1;)
				{
					sCurrString = oStringList[i];
					if (sCurrString == "")
					{
						oStringList.RemoveAt(i);
						continue;
					}
					else if (sCurrString.Contains("_"))
					{
						sPrefixString = "";
						arrSplitString = Regex.Split(sCurrString, "[_]");
						for (int k=0; k < arrSplitString.Length-1; k++)
						{
							sPrefixString += arrSplitString[k] + "_";
						}

						for (int j=i+1; j < oStringList.Count;)
						{
							sNextString = oStringList[j];
							if (sNextString == "")
							{
								oStringList.RemoveAt(j);
								continue;
							}

							if (sNextString.Contains(sPrefixString))
							{
								oStringList[i] += ", " + oStringList[j].Substring(sPrefixString.Length);
								oStringList.RemoveAt(j);
								continue;
							}

							j++;
						}
					}

					i++;
				}
			}
		}

		/// <summary>
		/// 返回两个字符串从0位置开始相同的子字符串
		/// </summary>
		/// <param name="sCurrString"></param>
		/// <param name="sNextString"></param>
		/// <returns></returns>
		private string GetSamePrefixString(string sString1, string sString2)
		{
			int iMinLength = 0;
			if (sString1.Length > iMinLength)
			{
				iMinLength = sString1.Length;
			}
			if (sString2.Length > iMinLength)
			{
				iMinLength = sString2.Length;
			}

			int i = 0;
			for (; i < iMinLength; i++)
			{
				if (sString1[i] != sString2[i])
				{
					break;
				}
			}

			return sString1.Substring(0, i);
		}

		/// <summary>
		/// 获取管路材料信息
		/// </summary>
		/// <param name="oPipeCompList"></param>
		/// <returns></returns>
		private DataTable GetNoneSpoolPipePartDataTable(List<BusinessObject> oPipeCompList, bool bIsComp = false)
		{
			DataTable oResultDT = new DataTable();
			oResultDT.Columns.Add("MaterialCode", typeof(string));
			oResultDT.Columns.Add("MaterialDesc", typeof(string));
			oResultDT.Columns.Add("NPD", typeof(double));
			oResultDT.Columns.Add("Quantity", typeof(double));

			//获取管材数据
			double iQuantity = 0.0;
			string sMaterialCode = "";
			string sMaterialDesc = "";
			double dNPD = 0.0;
			Part oPipeStockPart = null;
			foreach (var oBO in oPipeCompList)
			{
				oPipeStockPart = GetRefPart(oBO) as Part;
				if (oPipeStockPart != null)
				{
					sMaterialCode = GetCompMatCode(oPipeStockPart);
					sMaterialDesc = GetCompMatDesc(oPipeStockPart);
					dNPD = GetCompNPD(oPipeStockPart);
				}
				else
				{
					sMaterialCode = oBO.ToString();
					sMaterialDesc = "No catalog data...";
					dNPD = 0.0;
				}

				if (bIsComp)
				{
					iQuantity = 1;
				}
				else
				{
					iQuantity = GetPipeCutLength(oBO)/1000;
				}

				DataRow drNewRow = oResultDT.NewRow();
				drNewRow["MaterialCode"] = sMaterialCode;
				drNewRow["MaterialDesc"] = sMaterialDesc;
				drNewRow["NPD"] = dNPD;
				drNewRow["Quantity"] = iQuantity;
				oResultDT.Rows.Add(drNewRow);
			}

			//汇总排序
			var myTable = from t in oResultDT.AsEnumerable()
						  group t by new
						  {
							  MaterialCode = t.Field<string>("MaterialCode"),
							  MaterialDesc = t.Field<string>("MaterialDesc"),
							  NPD = t.Field<double>("NPD"),
						  } into x
						  orderby x.Key.MaterialCode, x.Key.NPD
						  select new
						  {
							  x.Key.MaterialCode,
							  x.Key.MaterialDesc,
							  x.Key.NPD,
							  Quantity = x.Sum(k => k.Field<double>("Quantity"))
						  };
			oResultDT = CommonFunctions.LINQToDataTable(myTable);

			return oResultDT;
		}

		/// <summary>
		/// 获取管部件参考原件对象
		/// </summary>
		/// <param name="oBO"></param>
		/// <returns></returns>
		private BusinessObject GetRefPart(BusinessObject oBO)
		{
			//可能存在参考原件被删除的情况
			try
			{
				return oBO.GetRelationship("madeFrom", "part").TargetObjects[0];
			}
			catch (System.Exception ex)
			{
				return null;
			}
		}

		/// <summary>
		/// 获取管材切割长度
		/// </summary>
		/// <param name="oBO"></param>
		/// <returns></returns>
		private double GetPipeCutLength(BusinessObject oBO)
		{
			PipeStockPart oPipe = oBO as PipeStockPart;
			return Math.Round(oPipe.StockPartCutLength * 1000, 0);
		}

		/// <summary>
		/// 获取管部件通径
		/// </summary>
		/// <param name="oPipe"></param>
		/// <returns></returns>
		private double GetCompNPD(BusinessObject oPipe)
		{
			return (oPipe.GetPropertyValue("IJDPipeComponent", "PrimarySize") as PropertyValueDouble).PropValue.Value;
		}

		/// <summary>
		/// 获取管部件材料描述
		/// </summary>
		/// <param name="oPipe"></param>
		/// <returns></returns>
		private string GetCompMatDesc(BusinessObject oPipe)
		{
			string sResult = (oPipe.GetPropertyValue("IJDPart", "PartDescription") as PropertyValueString).PropValue;
			if (sResult == "")
			{
				//描述没有就填写PartNumber
				sResult = (oPipe.GetPropertyValue("IJDPart", "PartNumber") as PropertyValueString).PropValue;
				if (sResult == "")
				{
					return "-";//为空时，显示为-
				}
			}

			return sResult;
		}

		/// <summary>
		/// 获取管部件材料编码
		/// </summary>
		/// <param name="oPipe"></param>
		/// <returns></returns>
		private string GetCompMatCode(BusinessObject oPipe)
		{
			string sResult = (oPipe.GetPropertyValue("IJIdentData", "MaterialsMgmtIdent") as PropertyValueString).PropValue;
			if (sResult == "")
			{
				return "-";//为空时，显示为-
			}
			else
			{
				return sResult;
			}
		}

		/// <summary>
		/// 获取管部件编号
		/// </summary>
		/// <param name="oPipe"></param>
		/// <returns></returns>
		private string GetCompPartNumber(BusinessObject oPipe)
		{
			return (oPipe.GetPropertyValue("IJDPart", "PartNumber") as PropertyValueString).PropValue;
		}

		/// <summary>
		/// 获取管部件的Note1
		/// </summary>
		/// <param name="oPipe"></param>
		/// <returns></returns>
		private string GetCompPartNote1(BusinessObject oPipe)
		{
			return (oPipe.GetPropertyValue("IJPipingNote", "PipingNote1") as PropertyValueString).PropValue;
		}

		/// <summary>
		/// 判断管路部件是否为外场件
		/// </summary>
		/// <param name="oBO"></param>
		/// <returns></returns>
		private bool IsErection(BusinessObject oBO)
		{
			if (oBO.SupportsInterface("IJFabricationInfo"))
			{
				PropertyValueCodelist propValueCodelist = oBO.GetPropertyValue("IJFabricationInfo", "FabricationType") as PropertyValueCodelist;
				if (propValueCodelist.PropertyInfo.CodeListInfo.GetCodelistItem(propValueCodelist.PropValue).ParentValue != 5)
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// 获取外场件名称和描述
		/// </summary>
		/// <param name="oBO"></param>
		/// <returns></returns>
		private void GetErectionNameAndDesc(BusinessObject oBO, ref string sName, ref string sDesc)
		{
			if ( oBO.SupportsInterface("IJNamedItem"))
			{
				//获取部件描述
				sName = ((PropertyValueString)oBO.GetPropertyValue("IJNamedItem", "Name")).PropValue;

				ReadOnlyCollection<BusinessObject> oTargets = oBO.GetRelationship("madeFrom", "part").TargetObjects;
				if (oTargets.Count > 0)
				{
					BusinessObject oMatCtrl = oTargets[0];
					string sTempDesc = ((PropertyValueString)oMatCtrl.GetPropertyValue("IJDPart", "PartDescription")).PropValue;
					string[] arrDesc = Regex.Split(sTempDesc, "[|]");
					if (Regex.Matches(sTempDesc, "[|]").Count > 1)
					{
						sDesc = arrDesc[1];
					}
				}
				if (sDesc == "")
				{
					oTargets = oBO.GetRelationship("PartOccToMaterialControlData", "MaterialControlData").TargetObjects;
					if (oTargets.Count > 0)
					{
						BusinessObject oMatCtrl = oTargets[0];
						sDesc = ((PropertyValueString)oMatCtrl.GetPropertyValue("IJGenericMaterialControlData", "ShortMaterialDescription")).PropValue;
					}
				}

				//如果是管部件，获取通径
				string sNPD = "";
				var oPipeComp = oBO as Ingr.SP3D.Route.Middle.PipeComponent;
				if (oPipeComp != null)
				{
					try
					{
						var oPipeNozzle = oPipeComp.GetPorts(PortType.Piping)[0] as PipeNozzle;
						sNPD = oPipeNozzle.NPD.Size.ToString() + oPipeNozzle.NPD.Units;
					}
					catch (System.Exception ex)
					{
						PipeRun oPipeRun = oPipeComp.GetRelationship("OwnsParts", "Owner").TargetObjects[0] as PipeRun;
						sNPD = oPipeRun.NPD.Size.ToString() + oPipeRun.NPD.Units;
					}
				}

				//组合描述和通径
				sDesc = sDesc + " " + sNPD;
			}
		}
	}

}
